/*
 * pointset_impl.h
 *
 *  Created on: Mar 1, 2011
 *      Author: tqlong
 */

#ifndef POINTSET_IMPL_H_
#define POINTSET_IMPL_H_
#include "pointset.h"
#include <fstream>

template <typename T>
void PointSet<T>::save(const std::string& fname)
{
  std::ofstream f(fname.c_str());
  save(f);
  f.close();
}

template <typename T>
void PointSet<T>::load(const std::string& fname)
{
  std::ifstream f(fname.c_str());
  load(f);
  f.close();
}

template <typename T>
void PointSet<T>::save(std::ostream& f)
{
  f << this->n() << " " << this->dim() << "\n";
  for (int i = 0; i < this->n(); i++) {
    (*this)[i].save(f);
    f << "\n";
  }
}

template <typename T>
void PointSet<T>::load(std::istream& f)
{
  int n;
  f >> n >> dim_;
  std::cout << "n = " << n << " dim = " << dim_ << "\n";
  this->clear();
  char line[100];
  f.getline(line, 100);
//  std::cout << "line = " << line << "\n";
  for (int i = 0; i < n && !f.eof(); i++) {
    this->push_back(vec_type(dim_));
    this->back().load(f);
  }
  assert(n == (int)this->size());
}

template <typename T>
void PointSet<T>::generate(int n, int dim, double noise)
{
  this->clear();
  dim_ = dim;
  for (int i = 0; i < n; i++) {
    this->push_back(vec_type(dim_));
    this->back().randn();
//    std::cerr << "vi="<<this->back() <<"\n";
    for (int d = 0; d < dim_; d++)
      if (fabs(this->back().get(d)) > 1e-10) {
//      std::cerr << d << " : " << this->back()[d] << " ";
        this->back().ref(d) *= arma::randn(1)[0]*10;
        this->back().ref(d) += arma::randn(1)[0]*10;
      }
//    std::cerr << "new vi="<<this->back() <<"\n";
  }
}

// ================ Point =================
template<typename T>
void Point<T>::save(const std::string& fname)
{
  std::ofstream f(fname.c_str());
  save(f);
  f.close();
}

template<typename T>
bool Point<T>::load(const std::string& fname)
{
  std::ifstream f(fname.c_str());
  bool ret = load(f);
  f.close();
  return ret;
}

template <typename S>
void save(S& f, const arma::vec& x)
{
  f << x.n_elem << " ";
  for (unsigned int i = 0; i < x.n_elem; i++)
    f << i << ":" << x[i] << " ";
}

template <typename S>
void load(S& f, arma::vec& x)
{
  int nnz;
  f >> nnz;
  x.zeros();
  for (int k = 0; k < nnz; k++) {
    unsigned int i;
    double val;
    char c;
    f >> i >> c >> val;
    assert(c == ':' && i < x.n_elem && i >= 0);
//    std::cout << "i = " << i << c << "val = " << val << " " << "\n";
    x[i] = val;
  }
}

template<typename T>
void Point<T>::save(std::ostream& f)
{
  ::save(f, *this);
}

template<typename T>
bool Point<T>::load(std::istream& f)
{
  std::string line;
  std::getline(f, line);
  if (line.empty()) return false;
//  std::cout << "line1 = " << line << "\n";
  std::istringstream s(line);
  ::load(s, *this);
  return true;
}
#endif /* POINTSET_IMPL_H_ */
